home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / sun4.md / vmSunAsm.s < prev    next >
Text File  |  1991-03-25  |  51KB  |  1,876 lines

  1. /*
  2.  * vmSun.s -
  3.  *
  4.  *    Subroutines to access Sun virtual memory mapping hardware.
  5.  *    All of the routines in here assume that source and destination
  6.  *    function codes are set to MMU space.
  7.  *
  8.  * Copyright (C) 1985 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #include "vmSunConst.h"
  13. #include "machAsmDefs.h"
  14.  
  15. .seg    "data"
  16. .asciz "$Header: /sprite/src/kernel/vm/sun4.md/RCS/vmSunAsm.s,v 9.7 90/12/07 12:54:32 mgbaker Exp $ SPRITE (Berkeley)"
  17. .align    8
  18. .seg    "text"
  19.  
  20. /*
  21.  * ----------------------------------------------------------------------------
  22.  *
  23.  * VmMachReadPTE --
  24.  *
  25.  *         Map the given hardware pmeg into the kernel's address space and 
  26.  *    return the pte at the corresponding address.  There is a reserved
  27.  *    address in the kernel that is used to map this hardware pmeg.
  28.  *
  29.  *    VmMachPTE VmMachReadPTE(pmegNum, addr)
  30.  *        int        pmegNum;    The pmeg to read the PTE for.
  31.  *        Address    addr;        The virtual address to read the PTE for.
  32.  *
  33.  * Results:
  34.  *     The value of the PTE.
  35.  *
  36.  * Side effects:
  37.  *     None.
  38.  *
  39.  * ----------------------------------------------------------------------------
  40.  */
  41. .globl    _VmMachReadPTE
  42. _VmMachReadPTE:
  43.     /* 
  44.      * Set the segment map entry.
  45.      */
  46.     set        _vmMachPTESegAddr, %OUT_TEMP1    /* Get access address */
  47.     ld        [%OUT_TEMP1], %OUT_TEMP1
  48. #ifdef sun4c
  49.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  50. #else
  51.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  52. #endif
  53.  
  54.     /*
  55.      * Get the page map entry.
  56.      */
  57.     lda        [%o1] VMMACH_PAGE_MAP_SPACE, %RETURN_VAL_REG    /* Return it */
  58.  
  59.     retl    /* Return from leaf routine */
  60.     nop
  61.  
  62. /*
  63.  * ----------------------------------------------------------------------------
  64.  *
  65.  * VmMachWritePTE --
  66.  *
  67.  *         Map the given hardware pmeg into the kernel's address space and 
  68.  *    write the pte at the corresponding address.  There is a reserved
  69.  *    address in the kernel that is used to map this hardware pmeg.
  70.  *
  71.  *    void VmMachWritePTE(pmegNum, addr, pte)
  72.  *        int           pmegNum;    The pmeg to write the PTE for.
  73.  *        Address    addr;        The address to write the PTE for.
  74.  *        VmMachPTE    pte;        The page table entry to write.
  75.  *
  76.  * Results:
  77.  *     None.
  78.  *
  79.  * Side effects:
  80.  *     The hardware page table entry is set.
  81.  *
  82.  * ----------------------------------------------------------------------------
  83.  */
  84. .globl    _VmMachWritePTE
  85. _VmMachWritePTE:
  86.     /* 
  87.      * Set the segment map entry.
  88.      */
  89.     set        _vmMachPTESegAddr, %OUT_TEMP1    /* Get access address */
  90.     ld        [%OUT_TEMP1], %OUT_TEMP1
  91. #ifdef sun4c
  92.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  93. #else
  94.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE /* Write seg map entry */
  95. #endif
  96.  
  97.     /*
  98.      * Set the page map entry.
  99.      */
  100.     /* place to write to */
  101.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP2
  102.     and        %o1, %OUT_TEMP2, %o1    /* Mask out low bits */
  103.     sta        %o2, [%o1] VMMACH_PAGE_MAP_SPACE
  104.  
  105.     retl    /* Return from leaf routine */
  106.     nop
  107.  
  108.  
  109. /*
  110.  * ----------------------------------------------------------------------
  111.  *
  112.  * bcopy --
  113.  *
  114.  *    Copy numBytes from *sourcePtr in to *destPtr.
  115.  *    This routine is optimized to do transfers when sourcePtr and 
  116.  *    destPtr are both double-word aligned.
  117.  *
  118.  *    void
  119.  *    bcopy(sourcePtr, destPtr, numBytes)
  120.  *        Address sourcePtr;          Where to copy from.
  121.  *        Address destPtr;            Where to copy to.
  122.  *        int numBytes;      The number of bytes to copy
  123.  *
  124.  * Results:
  125.  *    None.
  126.  *
  127.  * Side effects:
  128.  *    The area that destPtr points to is modified.
  129.  *
  130.  * ----------------------------------------------------------------------
  131.  */
  132. .globl    _bcopy
  133. _bcopy:
  134.                         /* sourcePtr in o0 */
  135.                         /* destPtr in o1 */
  136.                         /* numBytes in o2 */
  137. /*
  138.  * If the source or dest are not double-word aligned then everything must be
  139.  * done as word or byte copies.
  140.  */
  141.     or        %o0, %o1, %OUT_TEMP1
  142.     andcc    %OUT_TEMP1, 7, %g0
  143.     be        BDoubleWordCopy
  144.     nop
  145.     andcc    %OUT_TEMP1, 3, %g0
  146.     be        BWordCopy
  147.     nop
  148.     ba        BByteCopyIt
  149.     nop
  150.  
  151.     /*
  152.      * Do as many 64-byte copies as possible.
  153.      */
  154.  
  155. BDoubleWordCopy:
  156.     cmp        %o2, 64
  157.     bl         BFinishWord
  158.     nop
  159.     ldd        [%o0], %OUT_TEMP1    /* uses out_temp1 and out_temp2 */
  160.     std        %OUT_TEMP1, [%o1]
  161.     ldd        [%o0 + 8], %OUT_TEMP1
  162.     std        %OUT_TEMP1, [%o1 + 8]
  163.     ldd        [%o0 + 16], %OUT_TEMP1
  164.     std        %OUT_TEMP1, [%o1 + 16]
  165.     ldd        [%o0 + 24], %OUT_TEMP1
  166.     std        %OUT_TEMP1, [%o1 + 24]
  167.     ldd        [%o0 + 32], %OUT_TEMP1
  168.     std        %OUT_TEMP1, [%o1 + 32]
  169.     ldd        [%o0 + 40], %OUT_TEMP1
  170.     std        %OUT_TEMP1, [%o1 + 40]
  171.     ldd        [%o0 + 48], %OUT_TEMP1
  172.     std        %OUT_TEMP1, [%o1 + 48]
  173.     ldd        [%o0 + 56], %OUT_TEMP1
  174.     std        %OUT_TEMP1, [%o1 + 56]
  175.     
  176.     sub       %o2, 64, %o2
  177.     add        %o0, 64, %o0
  178.     add        %o1, 64, %o1
  179.     ba         BDoubleWordCopy
  180.     nop
  181. BWordCopy:
  182.     cmp        %o2, 64
  183.     bl        BFinishWord
  184.     nop
  185.     ld        [%o0], %OUT_TEMP1
  186.     st        %OUT_TEMP1, [%o1]
  187.     ld        [%o0 + 4], %OUT_TEMP1
  188.     st        %OUT_TEMP1, [%o1 + 4]
  189.     ld        [%o0 + 8], %OUT_TEMP1
  190.     st        %OUT_TEMP1, [%o1 + 8]
  191.     ld        [%o0 + 12], %OUT_TEMP1
  192.     st        %OUT_TEMP1, [%o1 + 12]
  193.     ld        [%o0 + 16], %OUT_TEMP1
  194.     st        %OUT_TEMP1, [%o1 + 16]
  195.     ld        [%o0 + 20], %OUT_TEMP1
  196.     st        %OUT_TEMP1, [%o1 + 20]
  197.     ld        [%o0 + 24], %OUT_TEMP1
  198.     st        %OUT_TEMP1, [%o1 + 24]
  199.     ld        [%o0 + 28], %OUT_TEMP1
  200.     st        %OUT_TEMP1, [%o1 + 28]
  201.     ld        [%o0 + 32], %OUT_TEMP1
  202.     st        %OUT_TEMP1, [%o1 + 32]
  203.     ld        [%o0 + 36], %OUT_TEMP1
  204.     st        %OUT_TEMP1, [%o1 + 36]
  205.     ld        [%o0 + 40], %OUT_TEMP1
  206.     st        %OUT_TEMP1, [%o1 + 40]
  207.     ld        [%o0 + 44], %OUT_TEMP1
  208.     st        %OUT_TEMP1, [%o1 + 44]
  209.     ld        [%o0 + 48], %OUT_TEMP1
  210.     st        %OUT_TEMP1, [%o1 + 48]
  211.     ld        [%o0 + 52], %OUT_TEMP1
  212.     st        %OUT_TEMP1, [%o1 + 52]
  213.     ld        [%o0 + 56], %OUT_TEMP1
  214.     st        %OUT_TEMP1, [%o1 + 56]
  215.     ld        [%o0 + 60], %OUT_TEMP1
  216.     st        %OUT_TEMP1, [%o1 + 60]
  217.     
  218.     sub       %o2, 64, %o2
  219.     add        %o0, 64, %o0
  220.     add        %o1, 64, %o1
  221.     ba         BWordCopy
  222.     nop
  223.  
  224.     /*
  225.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  226.      * quickly by dispatching into the middle of a sequence of move
  227.      * instructions, but I don't yet.
  228.      */
  229.  
  230. BFinishWord:
  231.     cmp        %o2, 4
  232.     bl        BByteCopyIt
  233.     nop
  234.     ld        [%o0], %OUT_TEMP1
  235.     st        %OUT_TEMP1, [%o1]
  236.     sub        %o2, 4, %o2
  237.     add        %o0, 4, %o0
  238.     add        %o1, 4, %o1
  239.     ba        BFinishWord
  240.     nop
  241.     
  242.     /*
  243.      * Do one byte copies until done.
  244.      */
  245. BByteCopyIt:
  246.     tst        %o2
  247.     ble         BDoneCopying
  248.     nop
  249.     ldub    [%o0], %OUT_TEMP1
  250.     stb        %OUT_TEMP1, [%o1]
  251.     sub        %o2, 1, %o2
  252.     add        %o0, 1, %o0
  253.     add        %o1, 1, %o1
  254.     ba         BByteCopyIt
  255.     nop
  256.  
  257.     /* 
  258.      * Return.
  259.      */
  260.  
  261. BDoneCopying: 
  262.     retl        /* return from leaf routine */
  263.     nop
  264.  
  265. /*
  266.  * ----------------------------------------------------------------------------
  267.  *
  268.  * VmMachGetPageMap --
  269.  *
  270.  *         Return the page map entry for the given virtual address.
  271.  *    It is assumed that the user context register is set to the context
  272.  *    for which the page map entry is to retrieved.
  273.  *
  274.  *    int Vm_GetPageMap(virtualAddress)
  275.  *        Address virtualAddress;
  276.  *
  277.  * Results:
  278.  *     The contents of the hardware page map entry.
  279.  *
  280.  * Side effects:
  281.  *     None.
  282.  *
  283.  * ----------------------------------------------------------------------------
  284.  */
  285. .globl    _VmMachGetPageMap
  286. _VmMachGetPageMap:
  287.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP1
  288.     and        %o0, %OUT_TEMP1, %o0    /* relevant bits from addr */
  289.     lda        [%o0] VMMACH_PAGE_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  290.  
  291.     retl                    /* Return */
  292.     nop
  293.  
  294. /*
  295.  * ----------------------------------------------------------------------------
  296.  *
  297.  * VmMachGetSegMap --
  298.  *
  299.  *         Return the segment map entry for the given virtual address.
  300.  *    It is assumed that the user context register is set to the context
  301.  *    for which the segment map entry is to retrieved.
  302.  *
  303.  *    int VmMachGetSegMap(virtualAddress)
  304.  *        Address virtualAddress;
  305.  *
  306.  * Results:
  307.  *     The contents of the segment map entry.
  308.  *
  309.  * Side effects:
  310.  *     None.
  311.  *
  312.  * ----------------------------------------------------------------------------
  313.  */
  314. .globl    _VmMachGetSegMap
  315. _VmMachGetSegMap:
  316.     set        VMMACH_SEG_MAP_MASK, %OUT_TEMP1
  317.     and        %o0, %OUT_TEMP1, %o0    /* Get relevant bits. */
  318. /* Is this necessary? */
  319. #ifdef sun4c
  320.     lduba    [%o0] VMMACH_SEG_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  321. #else
  322.     lduha    [%o0] VMMACH_SEG_MAP_SPACE, %RETURN_VAL_REG    /* read it */
  323. #endif
  324.  
  325.     retl        /* Return from leaf routine */
  326.     nop
  327.  
  328. /*
  329.  * ----------------------------------------------------------------------------
  330.  *
  331.  * VmMachSetPageMap --
  332.  *
  333.  *         Set the page map entry for the given virtual address to the pte valud 
  334.  *      given in pte.  It is assumed that the user context register is 
  335.  *    set to the context for which the page map entry is to be set.
  336.  *
  337.  *    void VmMachSetPageMap(virtualAddress, pte)
  338.  *        Address     virtualAddress;
  339.  *        VmMachPTE    pte;
  340.  *
  341.  * Results:
  342.  *     None.
  343.  *
  344.  * Side effects:
  345.  *     The hardware page map entry is set.
  346.  *
  347.  * ----------------------------------------------------------------------------
  348.  */
  349. .globl    _VmMachSetPageMap
  350. _VmMachSetPageMap:
  351.     set        VMMACH_PAGE_MAP_MASK, %OUT_TEMP1
  352.     and        %o0, %OUT_TEMP1, %o0    /* Mask out low bits */
  353.     sta        %o1, [%o0] VMMACH_PAGE_MAP_SPACE    /* write map entry */
  354.  
  355.     retl        /* Return from leaf routine */
  356.     nop
  357.  
  358. /*
  359.  * ----------------------------------------------------------------------------
  360.  *
  361.  * VmMachPMEGZero --
  362.  *
  363.  *         Set all of the page table entries in the pmeg to 0.  There is a special
  364.  *    address in the kernel's address space (vmMachPMEGSegAddr) that is used
  365.  *    to map the pmeg in so that it can be zeroed.
  366.  *
  367.  *    void VmMachPMEGZero(pmeg)
  368.  *        int pmeg;
  369.  *
  370.  * Results:
  371.  *     None.
  372.  *
  373.  * Side effects:
  374.  *     The given pmeg is zeroed.
  375.  *
  376.  * ----------------------------------------------------------------------------
  377.  */
  378.  
  379. .globl    _VmMachPMEGZero
  380. _VmMachPMEGZero:
  381.     /* Write segment map entry */
  382.     set        _vmMachPMEGSegAddr, %OUT_TEMP1
  383.     ld        [%OUT_TEMP1], %OUT_TEMP1
  384. #ifdef sun4c
  385.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE
  386. #else
  387.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE
  388. #endif
  389.  
  390.     /*
  391.      * Now zero out all page table entries.  %OUT_TEMP1 is starting address
  392.      * and %OUT_TEMP2 is ending address.
  393.      */
  394.     
  395.     set        VMMACH_SEG_SIZE, %OUT_TEMP2
  396.     add        %OUT_TEMP1, %OUT_TEMP2, %OUT_TEMP2
  397.  
  398. KeepZeroing:
  399.     sta        %g0, [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE
  400.     set        VMMACH_PAGE_SIZE_INT, %g1
  401.     add        %OUT_TEMP1, %g1, %OUT_TEMP1
  402.     cmp        %OUT_TEMP1, %OUT_TEMP2
  403. #ifdef NOTDEF
  404.     bl        KeepZeroing
  405. #else
  406.     bcs        KeepZeroing
  407. #endif NOTDEF
  408.     nop
  409.  
  410.     retl    /* Return from leaf routine */
  411.     nop
  412.  
  413. /*
  414.  * ----------------------------------------------------------------------------
  415.  *
  416.  * VmMachReadAndZeroPMEG --
  417.  *
  418.  *    Read out all page table entries in the given pmeg and then set each to
  419.  *    zero. There is a special address in the kernel's address space 
  420.  *    (vmMachPMEGSegAddr) that is used to access the PMEG.
  421.  *
  422.  *    void VmMachPMEGZero(pmeg, pteArray)
  423.  *        int     pmeg;
  424.  *        VmMachPTE    pteArray[VMMACH_NUM_PAGES_PER_SEG];
  425.  *
  426.  * Results:
  427.  *      None.
  428.  *
  429.  * Side effects:
  430.  *     The given pmeg is zeroed and *pteArray is filled in with the contents
  431.  *    of the PMEG before it is zeroed.
  432.  *
  433.  * ----------------------------------------------------------------------------
  434.  */
  435.  
  436. .globl    _VmMachReadAndZeroPMEG
  437. _VmMachReadAndZeroPMEG:
  438.     /*
  439.      * %OUT_TEMP1 is address.  %OUT_TEMP2 is a counter.
  440.      */
  441.     set        _vmMachPMEGSegAddr, %OUT_TEMP1
  442.     ld        [%OUT_TEMP1], %OUT_TEMP1
  443. #ifdef sun4c
  444.     stba    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write PMEG */
  445. #else
  446.     stha    %o0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write PMEG */
  447. #endif
  448.  
  449.     set        VMMACH_NUM_PAGES_PER_SEG_INT, %OUT_TEMP2
  450. KeepZeroing2:
  451.     lda        [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE, %o0    /* Read out the pte */
  452.     st        %o0, [%o1]                /* pte into array */
  453.     add        %o1, 4, %o1            /* increment array */
  454.     sta        %g0, [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE    /* Clear out the pte. */
  455.     set        VMMACH_PAGE_SIZE_INT, %g1
  456.     add        %OUT_TEMP1, %g1, %OUT_TEMP1    /* next addr */
  457.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2
  458.     bg        KeepZeroing2
  459.     nop
  460.  
  461.     retl    /* Return from leaf routine */            
  462.     nop
  463.  
  464. #ifdef NOTDEF
  465. /*
  466.  * ----------------------------------------------------------------------------
  467.  *
  468.  * VmMachTracePMEG --
  469.  *
  470.  *    Read out all page table entries in the given pmeg, generate trace
  471.  *    records for each with ref or mod bit set and then clear the ref
  472.  *    and mod bits.
  473.  *
  474.  *    void VmMachTracePMEG(pmeg)
  475.  *
  476.  * Results:
  477.  *      None.
  478.  *
  479.  * Side effects:
  480.  *    The reference and modified bits are cleared for all pages in
  481.  *    this PMEG.
  482.  *
  483.  * ----------------------------------------------------------------------------
  484.  */
  485.  
  486. #define    PTE_MASK (VMMACH_RESIDENT_BIT + VMMACH_REFERENCED_BIT + VMMACH_MODIFIED_BIT)
  487.  
  488. .globl    _VmMachTracePMEG
  489. _VmMachTracePMEG:
  490.     /* Start prologue */
  491.     set        (-MACH_SAVED_WINDOW_SIZE), %g1
  492.     save    %sp, %g1, %sp
  493.     /* end prologue */
  494.  
  495.     /* OUT_TEMP1 is addr */
  496.     set        _vmMachPMEGSegAddr, %OUT_TEMP1
  497.     ld        [%OUT_TEMP1], %OUT_TEMP1
  498. #ifdef sun4c
  499.     stba    %i0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write pmeg */
  500. #else
  501.     stha    %i0, [%OUT_TEMP1] VMMACH_SEG_MAP_SPACE    /* Write pmeg */
  502. #endif
  503.  
  504.     /* o1 is counter = second param */
  505.     set        VMMACH_NUM_PAGES_PER_SEG_INT, %o1
  506. TryTrace:
  507.     /* VOL_TEMP1 is pte read out = d2 */
  508.     lda        [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE, %VOL_TEMP1    /* Read pte */
  509.  
  510.     /*
  511.      * Trace this page if it is resident and the reference and modify bits
  512.      * are set.
  513.      */
  514.     /* OUT_TEMP2 is temp = d0 */
  515.     andcc    %VOL_TEMP1, PTE_MASK, %OUT_TEMP2
  516.     be        SkipPage
  517.     nop
  518.     cmp        %OUT_TEMP2, VMMACH_RESIDENT_BIT        /* BUG!!!!!! */
  519.     be        SkipPage
  520.     nop
  521.     mov        %VOL_TEMP1, %o0        /* pte in o0, pageNum in o1 */
  522.                     /* Clear the ref and mod bits. */
  523.     and        %VOL_TEMP1, ~(VMMACH_REFERENCED_BIT + VMMACH_MODIFIED_BIT), %VOL_TEMP1
  524.     sta        %VOL_TEMP1, [%OUT_TEMP1] VMMACH_PAGE_MAP_SPACE
  525.     call    _VmMachTracePage, 2        /* VmMachTrace(pte, pageNum) */
  526.     nop
  527.  
  528. SkipPage:
  529.     /* 
  530.      * Go to the next page.
  531.      */
  532.     add        %OUT_TEMP1, VMMACH_PAGE_SIZE_INT, %OUT_TEMP1    /* next addr */
  533.     subcc    %o1, 1, %o1
  534.     bg        TryTrace
  535.     nop
  536.  
  537.     ret            
  538.     restore
  539. #endif NOTDEF
  540.  
  541. /*
  542.  * ----------------------------------------------------------------------------
  543.  *
  544.  * VmMachSetSegMap --
  545.  *
  546.  *         Set the segment map entry for the given virtual address to the given 
  547.  *    value.  It is assumed that the user context register is set to the 
  548.  *    context for which the segment map entry is to be set.
  549.  *
  550.  *    void VmMachSetSegMap(virtualAddress, value)
  551.  *        Address    virtualAddress;
  552.  *        int        value;
  553.  *
  554.  * Results:
  555.  *     None.
  556.  *
  557.  * Side effects:
  558.  *     Hardware segment map entry for the current user context is set.
  559.  *
  560.  * ----------------------------------------------------------------------------
  561.  */
  562. .globl    _VmMachSetSegMap
  563. _VmMachSetSegMap:
  564. #ifdef sun4c
  565.     stba    %o1, [%o0] VMMACH_SEG_MAP_SPACE        /* write value to map */
  566. #else
  567.     stha    %o1, [%o0] VMMACH_SEG_MAP_SPACE        /* write value to map */
  568. #endif
  569.  
  570.     retl    /* return from leaf routine */
  571.     nop
  572.  
  573. /*
  574.  * ----------------------------------------------------------------------------
  575.  *
  576.  * VmMachCopyUserSegMap --
  577.  *
  578.  *         Copy the software segment map entries into the hardware segment entries.
  579.  *    All segment table entries for user address space up to the bottom of
  580.  *    the hole in the virtual address space are copied.
  581.  *    It is assumed that the user context register is 
  582.  *    set to the context for which the segment map entries are to be set.
  583.  *    
  584.  *    void VmMachCopyUserSegMap(tablePtr)
  585.  *        unsigned short *tablePtr;
  586.  *
  587.  * Results:
  588.  *     None.
  589.  *
  590.  * Side effects:
  591.  *     Hardware segment map entries for the current user context are set.
  592.  *
  593.  * ----------------------------------------------------------------------------
  594.  */
  595. .globl _VmMachCopyUserSegMap
  596. _VmMachCopyUserSegMap:
  597.     /*
  598.      * Due to the hole in the address space, I must make sure that no
  599.      * segment for an address in the hole gets anything written to it, since
  600.      * this would overwrite the pmeg mapping for a valid address's segment.
  601.      */
  602.  
  603.     /* Start prologue */
  604.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  605.     save    %sp, %OUT_TEMP1, %sp
  606.     /* end prologue */
  607.                         /* segTableAddr in %i0 */
  608.  
  609.     set        VMMACH_BOTTOM_OF_HOLE, %OUT_TEMP2    /* contains end addr */
  610.     srl        %OUT_TEMP2, VMMACH_SEG_SHIFT, %OUT_TEMP1    /* num segs */
  611.  
  612.     /* panic if not divisable by 8, since we do 8 at a time in loop */
  613.     andcc    %OUT_TEMP1, 7, %g0
  614.     be        StartCopySetup
  615.     nop
  616.     /*    Call panic - what args? */
  617.     clr        %o0
  618.     call    _panic, 1
  619.     nop
  620.  
  621. StartCopySetup:
  622.     /* preload offsets - each another seg size away */
  623.     set        VMMACH_SEG_SIZE, %i1
  624.     add        %i1, %i1, %i2
  625.     add        %i1, %i2, %i3
  626.     add        %i1, %i3, %i4
  627.     add        %i1, %i4, %i5
  628.     add        %i1, %i5, %o1
  629.     add        %i1, %o1, %o2
  630.     clr        %o0
  631. CopyLoop:
  632. #ifdef sun4c
  633.     lduh    [%i0], %OUT_TEMP1
  634.     stba    %OUT_TEMP1, [%o0] VMMACH_SEG_MAP_SPACE
  635.     lduh    [%i0 + 2], %OUT_TEMP1
  636.     stba    %OUT_TEMP1, [%o0 + %i1] VMMACH_SEG_MAP_SPACE
  637.     lduh    [%i0 + 4], %OUT_TEMP1
  638.     stba    %OUT_TEMP1, [%o0 + %i2] VMMACH_SEG_MAP_SPACE
  639.     lduh    [%i0 + 6], %OUT_TEMP1
  640.     stba    %OUT_TEMP1, [%o0 + %i3] VMMACH_SEG_MAP_SPACE
  641.     lduh    [%i0 + 8], %OUT_TEMP1
  642.     stba    %OUT_TEMP1, [%o0 + %i4] VMMACH_SEG_MAP_SPACE
  643.     lduh    [%i0 + 10], %OUT_TEMP1
  644.     stba    %OUT_TEMP1, [%o0 + %i5] VMMACH_SEG_MAP_SPACE
  645.     lduh    [%i0 + 12], %OUT_TEMP1
  646.     stba    %OUT_TEMP1, [%o0 + %o1] VMMACH_SEG_MAP_SPACE
  647.     lduh    [%i0 + 14], %OUT_TEMP1
  648.     stba    %OUT_TEMP1, [%o0 + %o2] VMMACH_SEG_MAP_SPACE
  649. #else
  650.     lduh    [%i0], %OUT_TEMP1
  651.     stha    %OUT_TEMP1, [%o0] VMMACH_SEG_MAP_SPACE
  652.     lduh    [%i0 + 2], %OUT_TEMP1
  653.     stha    %OUT_TEMP1, [%o0 + %i1] VMMACH_SEG_MAP_SPACE
  654.     lduh    [%i0 + 4], %OUT_TEMP1
  655.     stha    %OUT_TEMP1, [%o0 + %i2] VMMACH_SEG_MAP_SPACE
  656.     lduh    [%i0 + 6], %OUT_TEMP1
  657.     stha    %OUT_TEMP1, [%o0 + %i3] VMMACH_SEG_MAP_SPACE
  658.     lduh    [%i0 + 8], %OUT_TEMP1
  659.     stha    %OUT_TEMP1, [%o0 + %i4] VMMACH_SEG_MAP_SPACE
  660.     lduh    [%i0 + 10], %OUT_TEMP1
  661.     stha    %OUT_TEMP1, [%o0 + %i5] VMMACH_SEG_MAP_SPACE
  662.     lduh    [%i0 + 12], %OUT_TEMP1
  663.     stha    %OUT_TEMP1, [%o0 + %o1] VMMACH_SEG_MAP_SPACE
  664.     lduh    [%i0 + 14], %OUT_TEMP1
  665.     stha    %OUT_TEMP1, [%o0 + %o2] VMMACH_SEG_MAP_SPACE
  666. #endif /* sun4c */
  667.  
  668.     set        (8 * VMMACH_SEG_SIZE), %OUT_TEMP1
  669.     add        %o0, %OUT_TEMP1, %o0
  670.     cmp        %o0, %OUT_TEMP2        /* compare against end addr */
  671.     blu        CopyLoop
  672.     add        %i0, 16, %i0        /* delay slot */
  673.  
  674.     ret
  675.     restore
  676.  
  677. /*
  678.  * ----------------------------------------------------------------------------
  679.  *
  680.  * VmMachGetContextReg --
  681.  *
  682.  *         Return the value of the context register.
  683.  *
  684.  *    int VmMachGetContextReg()
  685.  *
  686.  * Results:
  687.  *     The value of context register.
  688.  *
  689.  * Side effects:
  690.  *     None.
  691.  *
  692.  * ----------------------------------------------------------------------------
  693.  */
  694.  
  695. .globl    _VmMachGetContextReg
  696. _VmMachGetContextReg:
  697.                     /* Move context reg into result reg  */
  698.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  699.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  700.  
  701.     retl        /* Return from leaf routine */
  702.     nop
  703.  
  704. /*
  705.  * ----------------------------------------------------------------------------
  706.  *
  707.  * VmMachSetContextReg --
  708.  *
  709.  *         Set the user and kernel context registers to the given value.
  710.  *
  711.  *    void VmMachSetContext(value)
  712.  *        int value;        Value to set register to
  713.  *
  714.  * Results:
  715.  *     None.
  716.  *
  717.  * Side effects:
  718.  *     None.
  719.  *
  720.  * ----------------------------------------------------------------------------
  721.  */
  722. .globl    _VmMachSetContextReg
  723. _VmMachSetContextReg:
  724.  
  725.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  726.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  727.  
  728.     retl        /* Return from leaf routine */
  729.     nop
  730.  
  731. /*
  732.  * ----------------------------------------------------------------------------
  733.  *
  734.  * VmMachGetUserContext --
  735.  *
  736.  *         Return the value of the user context register.
  737.  *
  738.  *    int VmMachGetUserContext()
  739.  *
  740.  * Results:
  741.  *     The value of user context register.
  742.  *
  743.  * Side effects:
  744.  *     None.
  745.  *
  746.  * ----------------------------------------------------------------------------
  747.  */
  748. .globl    _VmMachGetUserContext
  749. _VmMachGetUserContext:
  750.     /* There is no separate user context register on the sun4. */
  751.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  752.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  753.     
  754.     retl            /* Return from leaf routine */
  755.     nop
  756.  
  757. /*
  758.  * ----------------------------------------------------------------------------
  759.  *
  760.  * VmMachGetKernelContext --
  761.  *
  762.  *         Return the value of the kernel context register.
  763.  *
  764.  *    int VmMachGetKernelContext()
  765.  *
  766.  * Results:
  767.  *     The value of kernel context register.
  768.  *
  769.  * Side effects:
  770.  *     None.
  771.  *
  772.  * ----------------------------------------------------------------------------
  773.  */
  774. .globl    _VmMachGetKernelContext
  775. _VmMachGetKernelContext:
  776.     /* There is no separate kernel context register on the sun4. */
  777.     set        VMMACH_CONTEXT_OFF, %RETURN_VAL_REG
  778.     lduba    [%RETURN_VAL_REG] VMMACH_CONTROL_SPACE, %RETURN_VAL_REG
  779.     retl
  780.     nop
  781.  
  782. /*
  783.  * ----------------------------------------------------------------------------
  784.  *
  785.  * VmMachSetUserContext --
  786.  *
  787.  *         Set the user context register to the given value.
  788.  *
  789.  *    void VmMachSetUserContext(value)
  790.  *        int value;         Value to set register to
  791.  *
  792.  * Results:
  793.  *     None.
  794.  *
  795.  * Side effects:
  796.  *     None.
  797.  *
  798.  * ----------------------------------------------------------------------------
  799.  */
  800.  
  801. .globl    _VmMachSetUserContext
  802. _VmMachSetUserContext:
  803.     /* There is no separate user context register on the sun4. */
  804.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  805.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  806.     retl            /* Return from leaf routine */
  807.     nop
  808.  
  809. /*
  810.  * ----------------------------------------------------------------------------
  811.  *
  812.  * VmMachSetKernelContext --
  813.  *
  814.  *         Set the kernel context register to the given value.
  815.  *
  816.  *    void VmMachSetKernelContext(value)
  817.  *        int value;        Value to set register to
  818.  *
  819.  * Results:
  820.  *     None.
  821.  *
  822.  * Side effects:
  823.  *     The supervisor context is set.
  824.  *
  825.  * ----------------------------------------------------------------------------
  826.  */
  827.  
  828. .globl    _VmMachSetKernelContext
  829. _VmMachSetKernelContext:
  830.     /* There is no separate kernel context register on the sun4. */
  831.     set        VMMACH_CONTEXT_OFF, %OUT_TEMP1
  832.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  833.     retl            /* Return from leaf routine */
  834.     nop
  835.  
  836. /*
  837.  * ----------------------------------------------------------------------------
  838.  *
  839.  * VmMachInitSystemEnableReg --
  840.  *
  841.  *         Set the system enable register to turn on caching, etc.
  842.  *
  843.  *    void VmMachInitSystemEnableReg()
  844.  *
  845.  * Results:
  846.  *     None.
  847.  *
  848.  * Side effects:
  849.  *     Caching will be turned on, if it wasn't already.
  850.  *
  851.  * ----------------------------------------------------------------------------
  852.  */
  853. .globl    _VmMachInitSystemEnableReg
  854. _VmMachInitSystemEnableReg:
  855.     set        VMMACH_SYSTEM_ENABLE_REG, %OUT_TEMP1
  856.     lduba    [%OUT_TEMP1] VMMACH_CONTROL_SPACE, %o0
  857. #ifdef sun4c
  858.     or        %o0, VMMACH_ENABLE_CACHE_BIT | VMMACH_ENABLE_DVMA_BIT, %o0
  859. #else
  860.     or          %o0, VMMACH_ENABLE_CACHE_BIT, %o0
  861. #endif
  862.     stba    %o0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  863.     retl            /* Return from leaf routine */
  864.     nop
  865.  
  866. #ifndef sun4c
  867. /* Not used in sun4c */
  868. /*
  869.  * ----------------------------------------------------------------------------
  870.  *
  871.  * VmMachInitAddrErrorControlReg --
  872.  *
  873.  *         Set the addr error control register to enable asynchronous memory
  874.  *    error reporting.
  875.  *
  876.  *    void VmMachInitAddrErrorControlReg()
  877.  *
  878.  * Results:
  879.  *     None.
  880.  *
  881.  * Side effects:
  882.  *     Asynchronous memory errors may now be reported.
  883.  *
  884.  * ----------------------------------------------------------------------------
  885.  */
  886. .globl    _VmMachInitAddrErrorControlReg
  887. _VmMachInitAddrErrorControlReg:
  888.     set        VMMACH_ADDR_CONTROL_REG, %OUT_TEMP1
  889.     ld        [%OUT_TEMP1], %OUT_TEMP2
  890.     or        %OUT_TEMP2, VMMACH_ENABLE_MEM_ERROR_BIT, %OUT_TEMP2
  891.     st        %OUT_TEMP2, [%OUT_TEMP1]
  892.     retl
  893.     nop
  894. #endif
  895.  
  896.  
  897.  
  898. /*
  899.  * ----------------------------------------------------------------------------
  900.  *
  901.  * VmMachClearCacheTags --
  902.  *
  903.  *         Clear all tags in the cache.
  904.  *
  905.  *    void VmMachClearCacheTags()
  906.  *
  907.  * Results:
  908.  *     None.
  909.  *
  910.  * Side effects:
  911.  *     None.
  912.  *
  913.  * ----------------------------------------------------------------------------
  914.  */
  915. .globl    _VmMachClearCacheTags
  916. _VmMachClearCacheTags:
  917.     set        VMMACH_CACHE_TAGS_ADDR, %OUT_TEMP1
  918.     set        VMMACH_NUM_CACHE_TAGS, %OUT_TEMP2
  919. ClearTags:
  920.     sta        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE        /* clear tag */
  921.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2            /* dec cntr */
  922.     bne        ClearTags
  923.     add        %OUT_TEMP1, VMMACH_CACHE_TAG_INCR, %OUT_TEMP1    /* delay slot */
  924.  
  925.     retl
  926.     nop
  927.  
  928. /*
  929.  * ----------------------------------------------------------------------------
  930.  *
  931.  * VmMach_FlushCurrentContext --
  932.  *
  933.  *         Flush the current context from the cache.
  934.  *
  935.  *    void VmMach_FlushCurrentContext()
  936.  *
  937.  * Results:
  938.  *     None.
  939.  *
  940.  * Side effects:
  941.  *     All data cached from the current context is flushed from the cache.
  942.  *
  943.  * ----------------------------------------------------------------------------
  944.  */
  945. .globl    _VmMach_FlushCurrentContext
  946. _VmMach_FlushCurrentContext:
  947.     /* Start prologue */
  948.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  949.     save    %sp, %OUT_TEMP1, %sp
  950.     /* end prologue */
  951.  
  952.     /*
  953.      * Spread the stores evenly through 16 chunks of the cache.  This helps
  954.      * to avoid back-to-back writebacks.
  955.      */
  956.     set        (VMMACH_CACHE_SIZE / 16), %l0
  957.  
  958.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  959.     sub        %l0, VMMACH_CACHE_LINE_SIZE, %i0
  960.  
  961.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  962.     add        %l0, %l0, %l1
  963.     add        %l1, %l0, %l2
  964.     add        %l2, %l0, %l3
  965.     add        %l3, %l0, %l4
  966.     add        %l4, %l0, %l5
  967.     add        %l5, %l0, %l6
  968.     add        %l6, %l0, %l7
  969.  
  970.     add        %l7, %l0, %o0
  971.     add        %o0, %l0, %o1
  972.     add        %o1, %l0, %o2
  973.     add        %o2, %l0, %o3
  974.     add        %o3, %l0, %o4
  975.     add        %o4, %l0, %o5
  976.     add        %o5, %l0, %i4
  977.  
  978.     sta        %g0, [%i0] VMMACH_FLUSH_CONTEXT_SPACE
  979. FlushingContext:
  980.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_CONTEXT_SPACE
  981.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_CONTEXT_SPACE
  982.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_CONTEXT_SPACE
  983.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_CONTEXT_SPACE
  984.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_CONTEXT_SPACE
  985.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_CONTEXT_SPACE
  986.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_CONTEXT_SPACE
  987.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_CONTEXT_SPACE
  988.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_CONTEXT_SPACE
  989.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_CONTEXT_SPACE
  990.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_CONTEXT_SPACE
  991.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_CONTEXT_SPACE
  992.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_CONTEXT_SPACE
  993.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_CONTEXT_SPACE
  994.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_CONTEXT_SPACE
  995.  
  996.     subcc    %i0, VMMACH_CACHE_LINE_SIZE, %i0    /* decrement loop */
  997.     bge,a    FlushingContext
  998.                             /* delay slot */
  999.     sta        %g0, [%i0] VMMACH_FLUSH_CONTEXT_SPACE
  1000.  
  1001.     ret
  1002.     restore
  1003.  
  1004.  
  1005. /*
  1006.  * ----------------------------------------------------------------------------
  1007.  *
  1008.  * VmMachFlushSegment --
  1009.  *
  1010.  *         Flush a segment from the cache.
  1011.  *
  1012.  *    void VmMachFlushSegment(segVirtAddr)
  1013.  *    Address    segVirtAddr;    (Address of segment)
  1014.  *
  1015.  * Results:
  1016.  *     None.
  1017.  *
  1018.  * Side effects:
  1019.  *     All data cached from the segment is flushed from the cache.
  1020.  *
  1021.  * ----------------------------------------------------------------------------
  1022.  */
  1023. .globl    _VmMachFlushSegment
  1024. _VmMachFlushSegment:
  1025.     /* Start prologue */
  1026.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  1027.     save    %sp, %OUT_TEMP1, %sp
  1028.     /* end prologue */
  1029.  
  1030.     set        VMMACH_SEG_MAP_MASK, %o0
  1031.     and        %i0, %o0, %i0                /* beginning of seg */
  1032.     
  1033.     set        VMMACH_NUM_CACHE_LINES / 16, %i1    /* num loops */
  1034.  
  1035.     /*
  1036.      * Spread the stores evenly through 16 chunks of the cache.  This helps
  1037.      * to avoid back-to-back writebacks.
  1038.      */
  1039.     set        (VMMACH_CACHE_SIZE / 16), %l0
  1040.  
  1041.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  1042.     add        %i0, %l0, %i0
  1043.     sub        %i0, VMMACH_CACHE_LINE_SIZE, %i0
  1044.  
  1045.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  1046.     add        %l0, %l0, %l1
  1047.     add        %l1, %l0, %l2
  1048.     add        %l2, %l0, %l3
  1049.     add        %l3, %l0, %l4
  1050.     add        %l4, %l0, %l5
  1051.     add        %l5, %l0, %l6
  1052.     add        %l6, %l0, %l7
  1053.  
  1054.     add        %l7, %l0, %o0
  1055.     add        %o0, %l0, %o1
  1056.     add        %o1, %l0, %o2
  1057.     add        %o2, %l0, %o3
  1058.     add        %o3, %l0, %o4
  1059.     add        %o4, %l0, %o5
  1060.     add        %o5, %l0, %i4
  1061.  
  1062. FlushingSegment:
  1063.     sta        %g0, [%i0] VMMACH_FLUSH_SEG_SPACE
  1064.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_SEG_SPACE
  1065.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_SEG_SPACE
  1066.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_SEG_SPACE
  1067.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_SEG_SPACE
  1068.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_SEG_SPACE
  1069.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_SEG_SPACE
  1070.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_SEG_SPACE
  1071.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_SEG_SPACE
  1072.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_SEG_SPACE
  1073.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_SEG_SPACE
  1074.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_SEG_SPACE
  1075.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_SEG_SPACE
  1076.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_SEG_SPACE
  1077.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_SEG_SPACE
  1078.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_SEG_SPACE
  1079.  
  1080.     subcc    %i1, 1, %i1                /* decrement loop */
  1081.     bne        FlushingSegment
  1082.                             /* delay slot */
  1083.     sub        %i0, VMMACH_CACHE_LINE_SIZE, %i0
  1084.  
  1085.     ret
  1086.     restore
  1087.  
  1088. /*
  1089.  * ----------------------------------------------------------------------------
  1090.  *
  1091.  * VmMach_FlushByteRange --
  1092.  *
  1093.  *         Flush a range of bytes from the cache.
  1094.  *
  1095.  *    void VmMachFlushByteRange(virtAddr, numBytes)
  1096.  *    Address    virtAddr;    (Address of page)
  1097.  *    int    numBytes;    (Number of bytes to flush)
  1098.  *
  1099.  * Results:
  1100.  *     None.
  1101.  *
  1102.  * Side effects:
  1103.  *     All data cached in the byte range is flushed.
  1104.  *
  1105.  * ----------------------------------------------------------------------------
  1106.  */
  1107. .globl    _VmMach_FlushByteRange
  1108. _VmMach_FlushByteRange:
  1109.     /* Start prologue */
  1110.     save    %sp, (-MACH_SAVED_WINDOW_SIZE), %sp
  1111.     /* end prologue */
  1112.  
  1113.     /* Address of last byte to flush */
  1114.     add        %i0, %i1, %OUT_TEMP2
  1115.     sub        %OUT_TEMP2, 1, %OUT_TEMP2
  1116.  
  1117.     /* Get first line to flush */
  1118.     set        ~(VMMACH_CACHE_LINE_SIZE - 1), %OUT_TEMP1
  1119.     and        %i0, %OUT_TEMP1, %i0
  1120.  
  1121.     /* Get last line to flush */
  1122.     and        %OUT_TEMP2, %OUT_TEMP1, %VOL_TEMP1
  1123.  
  1124.     /* Get number of lines to flush */
  1125.     sub        %VOL_TEMP1, %i0, %OUT_TEMP2
  1126.     srl        %OUT_TEMP2, VMMACH_CACHE_SHIFT, %OUT_TEMP2
  1127.     add        %OUT_TEMP2, 1, %i3
  1128.  
  1129.     /* Do we have at least 16 lines to flush? */
  1130.     subcc    %i3, 16, %g0
  1131.     bl        FinishFlushing
  1132.     nop
  1133.  
  1134.     set        VMMACH_CACHE_LINE_SIZE, %l0
  1135.     add        %l0, VMMACH_CACHE_LINE_SIZE, %l1
  1136.     add        %l1, VMMACH_CACHE_LINE_SIZE, %l2
  1137.     add        %l2, VMMACH_CACHE_LINE_SIZE, %l3
  1138.     add        %l3, VMMACH_CACHE_LINE_SIZE, %l4
  1139.     add        %l4, VMMACH_CACHE_LINE_SIZE, %l5
  1140.     add        %l5, VMMACH_CACHE_LINE_SIZE, %l6
  1141.     add        %l6, VMMACH_CACHE_LINE_SIZE, %l7
  1142.     add        %l7, VMMACH_CACHE_LINE_SIZE, %o0
  1143.     add        %o0, VMMACH_CACHE_LINE_SIZE, %o1
  1144.     add        %o1, VMMACH_CACHE_LINE_SIZE, %o2
  1145.     add        %o2, VMMACH_CACHE_LINE_SIZE, %o3
  1146.     add        %o3, VMMACH_CACHE_LINE_SIZE, %o4
  1147.     add        %o4, VMMACH_CACHE_LINE_SIZE, %o5
  1148.     add        %o5, VMMACH_CACHE_LINE_SIZE, %i4
  1149.  
  1150. FlushingHere:
  1151.     /* We have at least 16 lines to flush. */
  1152.     sub        %i3, 16, %i3
  1153.  
  1154.     /* Try to space them out to avoid back-to-back copies. */
  1155.  
  1156.     /*
  1157.      * Is this far enough spaced??  How many lines on average will the routine
  1158.      * be asked to flush?
  1159.      */
  1160.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1161.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_PAGE_SPACE
  1162.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_PAGE_SPACE
  1163.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_PAGE_SPACE
  1164.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_PAGE_SPACE
  1165.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_PAGE_SPACE
  1166.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_PAGE_SPACE
  1167.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_PAGE_SPACE
  1168.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_PAGE_SPACE
  1169.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_PAGE_SPACE
  1170.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_PAGE_SPACE
  1171.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_PAGE_SPACE
  1172.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_PAGE_SPACE
  1173.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_PAGE_SPACE
  1174.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_PAGE_SPACE
  1175.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_PAGE_SPACE
  1176.  
  1177.     /* Are there another 16 lines? */
  1178.     subcc       %i3, 16, %g0
  1179.     bge        FlushingHere
  1180.     add        %i0, (16 * VMMACH_CACHE_LINE_SIZE), %i0        /* delay slot */
  1181.     tst        %i3
  1182.     be        DoneFlushing    /* We finished with the last 16 lines... */
  1183.     nop
  1184. FinishFlushing:
  1185.     /* Finish the rest line by line.  Should I optimize here?  How much? */
  1186.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1187.     subcc    %i3, 1, %i3
  1188.     bg        FinishFlushing
  1189.     add        %i0, VMMACH_CACHE_LINE_SIZE, %i0        /* delay slot */
  1190.  
  1191. DoneFlushing:
  1192.     ret
  1193.     restore
  1194.  
  1195. /*
  1196.  * ----------------------------------------------------------------------------
  1197.  *
  1198.  * VmMachFlushPage --
  1199.  *
  1200.  *         Flush a page from the cache.
  1201.  *
  1202.  *    void VmMachFlushPage(pageVirtAddr)
  1203.  *    Address    pageVirtAddr;    (Address of page)
  1204.  *
  1205.  * Results:
  1206.  *     None.
  1207.  *
  1208.  * Side effects:
  1209.  *     All data cached from the page is flushed from the cache.
  1210.  *
  1211.  * ----------------------------------------------------------------------------
  1212.  */
  1213. .globl    _VmMachFlushPage
  1214. _VmMachFlushPage:
  1215.     /* Start prologue */
  1216.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP1
  1217.     save    %sp, %OUT_TEMP1, %sp
  1218.     /* end prologue */
  1219.     
  1220.     set        ~VMMACH_OFFSET_MASK, %o0
  1221.     and        %i0, %o0, %i0            /* beginning of page */
  1222.  
  1223.                         /* number of loops */
  1224.     set        (VMMACH_PAGE_SIZE_INT / VMMACH_CACHE_LINE_SIZE / 16), %i1
  1225.  
  1226.     /*
  1227.      * Spread the stores evenly through 16 chunks of the page flush area in the
  1228.      * cache.  This helps to avoid back-to-back writebacks.
  1229.      */
  1230.     set        (VMMACH_PAGE_SIZE_INT / 16), %l0
  1231.  
  1232.     /* Start with last line in each of the 16 chunks.  We work backwards. */
  1233.     add        %i0, %l0, %i0
  1234.     sub        %i0, VMMACH_CACHE_LINE_SIZE, %i0
  1235.  
  1236.     /* Preload a bunch of offsets so we can straight-line a lot of this. */
  1237.     add        %l0, (VMMACH_PAGE_SIZE_INT / 16), %l1
  1238.     add        %l1, (VMMACH_PAGE_SIZE_INT / 16), %l2
  1239.     add        %l2, (VMMACH_PAGE_SIZE_INT / 16), %l3
  1240.     add        %l3, (VMMACH_PAGE_SIZE_INT / 16), %l4
  1241.     add        %l4, (VMMACH_PAGE_SIZE_INT / 16), %l5
  1242.     add        %l5, (VMMACH_PAGE_SIZE_INT / 16), %l6
  1243.     add        %l6, (VMMACH_PAGE_SIZE_INT / 16), %l7
  1244.  
  1245.     add        %l7, (VMMACH_PAGE_SIZE_INT / 16), %o0
  1246.     add        %o0, (VMMACH_PAGE_SIZE_INT / 16), %o1
  1247.     add        %o1, (VMMACH_PAGE_SIZE_INT / 16), %o2
  1248.     add        %o2, (VMMACH_PAGE_SIZE_INT / 16), %o3
  1249.     add        %o3, (VMMACH_PAGE_SIZE_INT / 16), %o4
  1250.     add        %o4, (VMMACH_PAGE_SIZE_INT / 16), %o5
  1251.     add        %o5, (VMMACH_PAGE_SIZE_INT / 16), %i4
  1252.  
  1253. FlushingPage:
  1254.     sta        %g0, [%i0] VMMACH_FLUSH_PAGE_SPACE
  1255.     sta        %g0, [%i0 + %l0] VMMACH_FLUSH_PAGE_SPACE
  1256.     sta        %g0, [%i0 + %l1] VMMACH_FLUSH_PAGE_SPACE
  1257.     sta        %g0, [%i0 + %l2] VMMACH_FLUSH_PAGE_SPACE
  1258.     sta        %g0, [%i0 + %l3] VMMACH_FLUSH_PAGE_SPACE
  1259.     sta        %g0, [%i0 + %l4] VMMACH_FLUSH_PAGE_SPACE
  1260.     sta        %g0, [%i0 + %l5] VMMACH_FLUSH_PAGE_SPACE
  1261.     sta        %g0, [%i0 + %l6] VMMACH_FLUSH_PAGE_SPACE
  1262.     sta        %g0, [%i0 + %l7] VMMACH_FLUSH_PAGE_SPACE
  1263.     sta        %g0, [%i0 + %o0] VMMACH_FLUSH_PAGE_SPACE
  1264.     sta        %g0, [%i0 + %o1] VMMACH_FLUSH_PAGE_SPACE
  1265.     sta        %g0, [%i0 + %o2] VMMACH_FLUSH_PAGE_SPACE
  1266.     sta        %g0, [%i0 + %o3] VMMACH_FLUSH_PAGE_SPACE
  1267.     sta        %g0, [%i0 + %o4] VMMACH_FLUSH_PAGE_SPACE
  1268.     sta        %g0, [%i0 + %o5] VMMACH_FLUSH_PAGE_SPACE
  1269.     sta        %g0, [%i0 + %i4] VMMACH_FLUSH_PAGE_SPACE
  1270.  
  1271.     subcc    %i1, 1, %i1                /* decrement loop */
  1272.     bne        FlushingPage
  1273.     sub        %i0, VMMACH_CACHE_LINE_SIZE, %i0    /* delay slot */
  1274.     ret
  1275.     restore
  1276. #ifndef sun4c
  1277. /*
  1278.  * ----------------------------------------------------------------------------
  1279.  *
  1280.  * VmMachSetup32BitDVMA --
  1281.  *
  1282.  *      Return the user DVMA to access the lower 256 megabytes of context 0.
  1283.  *    We use this space to map pages for DMA.
  1284.  *
  1285.  *
  1286.  * Results:
  1287.  *     None.
  1288.  *
  1289.  * Side effects:
  1290.  *     None.
  1291.  *
  1292.  * ----------------------------------------------------------------------------
  1293.  */
  1294.  
  1295. .globl  _VmMachSetup32BitDVMA
  1296. _VmMachSetup32BitDVMA:
  1297.     /*
  1298.      * First we initialized the map for VME context 0 to map into the
  1299.      * lower 256 megabytes of the context 0. The DVMA map takes the form
  1300.      * of an eight element array index by bits 30 to 28 from the VME bus. 
  1301.      *  each entry looking like:
  1302.      *   struct 32BitDVMAMap {
  1303.      *        unsigned char  :4;
  1304.      *        unsigned char  topNibble:4;   Top four bits of DMA address. 
  1305.      *        unsigned char  context:8;     Context to access. 
  1306.      * }
  1307.      *        
  1308.      * We initialized the following mapping:
  1309.      * VME 32 addresses 0x80000000 - 0x8fffffff to 0 - 0x0fffffff of context 0.
  1310.      */
  1311.     set         VMMACH_USER_DVMA_MAP, %OUT_TEMP1
  1312.     stba        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1313.     add        %OUT_TEMP1,1,%OUT_TEMP1
  1314.     stba        %g0, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1315.  
  1316.     /*
  1317.      * Enable user DVMA from VME context 0 (ie 0x80000000 - 0x8fffffff)
  1318.      * The User DVMA enable register takes the form of a bitmap will one
  1319.      * bit per VME context.
  1320.      */
  1321.     set         VMMACH_USER_DVMA_ENABLE_REG, %OUT_TEMP1
  1322.     mov        1, %OUT_TEMP2
  1323.     stba        %OUT_TEMP2, [%OUT_TEMP1] VMMACH_CONTROL_SPACE
  1324.  
  1325.     retl                /* Return from leaf routine */
  1326.     nop
  1327.  
  1328. #endif
  1329. /*
  1330.  * ----------------------------------------------------------------------
  1331.  *
  1332.  * VmMachQuickNDirtyCopy --
  1333.  *
  1334.  *    Copy numBytes from *sourcePtr in to *destPtr, with accesses to sourcePtr
  1335.  *    in sourceContext and accesses to destPtr in destContext.
  1336.  *    This routine is optimized to do transfers when sourcePtr and 
  1337.  *    destPtr are both double-word aligned.
  1338.  *
  1339.  *    ReturnStatus
  1340.  *    VmMachQuickNDirtyCopy(numBytes, sourcePtr, destPtr, sourceContext,
  1341.  *                                destContext)
  1342.  *        register int numBytes;      The number of bytes to copy
  1343.  *        Address sourcePtr;          Where to copy from.
  1344.  *        Address destPtr;            Where to copy to.
  1345.  *        unsigned int sourceContext;    Context to access source in.
  1346.  *        unsigned int destContext;    Context to access dest in.
  1347.  *
  1348.  * Results:
  1349.  *    Returns SUCCESS if the copy went OK (which should be often).  If
  1350.  *    a bus error (INCLUDING a page fault) occurred while reading or
  1351.  *    writing user memory, then FAILURE is returned (this return
  1352.  *    occurs from the trap handler, rather than from this procedure).
  1353.  *
  1354.  * Side effects:
  1355.  *    The area that destPtr points to is modified.
  1356.  *
  1357.  * ----------------------------------------------------------------------
  1358.  */
  1359. .globl _VmMachQuickNDirtyCopy
  1360. _VmMachQuickNDirtyCopy:
  1361.     /* Start prologue */
  1362.     set        (-MACH_SAVED_WINDOW_SIZE), %OUT_TEMP2
  1363.     save    %sp, %OUT_TEMP2, %sp
  1364.     /* end prologue */
  1365.                         /* numBytes in i0 */
  1366.                         /* sourcePtr in i1 */
  1367.                         /* destPtr in i2 */
  1368.                         /* sourceContext in i3 */
  1369.                         /* destContext in i4 */
  1370.  
  1371.     /* use %i5 for context reg offset */
  1372.     set        VMMACH_CONTEXT_OFF, %i5
  1373.  
  1374. /*
  1375.  * If the source or dest are not double-word aligned then everything must be
  1376.  * done as word or byte copies.
  1377.  */
  1378.     or        %i1, %i2, %OUT_TEMP1
  1379.     andcc    %OUT_TEMP1, 7, %g0
  1380.     be        QDoubleWordCopy
  1381.     nop
  1382.     andcc    %OUT_TEMP1, 3, %g0
  1383.     be        QWordCopy
  1384.     nop
  1385.     ba        QByteCopyIt
  1386.     nop
  1387.  
  1388.     /*
  1389.      * Do as many 64-byte copies as possible.
  1390.      */
  1391.  
  1392. QDoubleWordCopy:
  1393.     cmp        %i0, 64
  1394.     bl         QFinishWord
  1395.     nop
  1396.  
  1397.     /* set context to sourceContext */
  1398.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1399.  
  1400.     ldd        [%i1], %l0
  1401.     ldd        [%i1 + 8], %l2
  1402.     ldd        [%i1 + 16], %l4
  1403.     ldd        [%i1 + 24], %l6
  1404.     ldd        [%i1 + 32], %o0
  1405.     ldd        [%i1 + 40], %o2
  1406.     ldd        [%i1 + 48], %o4
  1407.     ldd        [%i1 + 56], %g6
  1408.     
  1409.     /* set context to destContext */
  1410.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1411.  
  1412.     std        %l0, [%i2]
  1413.     std        %l2, [%i2 + 8]
  1414.     std        %l4, [%i2 + 16]
  1415.     std        %l6, [%i2 + 24]
  1416.     std        %o0, [%i2 + 32]
  1417.     std        %o2, [%i2 + 40]
  1418.     std        %o4, [%i2 + 48]
  1419.     std        %g6, [%i2 + 56]
  1420.  
  1421.     sub       %i0, 64, %i0
  1422.     add        %i1, 64, %i1
  1423.     add        %i2, 64, %i2
  1424.     ba         QDoubleWordCopy
  1425.     nop
  1426. QWordCopy:
  1427.     cmp        %i0, 64
  1428.     bl        QFinishWord
  1429.     nop
  1430.  
  1431.     /* from context */
  1432.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1433.  
  1434.     ld        [%i1], %l0
  1435.     ld        [%i1 + 4], %l1
  1436.     ld        [%i1 + 8], %l2
  1437.     ld        [%i1 + 12], %l3
  1438.     ld        [%i1 + 16], %l4
  1439.     ld        [%i1 + 20], %l5
  1440.     ld        [%i1 + 24], %l6
  1441.     ld        [%i1 + 28], %l7
  1442.  
  1443.     /* to context */
  1444.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1445.  
  1446.     st        %l0, [%i2]
  1447.     st        %l1, [%i2 + 4]
  1448.     st        %l2, [%i2 + 8]
  1449.     st        %l3, [%i2 + 12]
  1450.     st        %l4, [%i2 + 16]
  1451.     st        %l5, [%i2 + 20]
  1452.     st        %l6, [%i2 + 24]
  1453.     st        %l7, [%i2 + 28]
  1454.  
  1455.     /* from context */
  1456.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1457.  
  1458.     ld        [%i1 + 32], %l0
  1459.     ld        [%i1 + 36], %l1
  1460.     ld        [%i1 + 40], %l2
  1461.     ld        [%i1 + 44], %l3
  1462.     ld        [%i1 + 48], %l4
  1463.     ld        [%i1 + 52], %l5
  1464.     ld        [%i1 + 56], %l6
  1465.     ld        [%i1 + 60], %l7
  1466.     
  1467.     /* to context */
  1468.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1469.  
  1470.     st        %l0, [%i2 + 32]
  1471.     st        %l1, [%i2 + 36]
  1472.     st        %l2, [%i2 + 40]
  1473.     st        %l3, [%i2 + 44]
  1474.     st        %l4, [%i2 + 48]
  1475.     st        %l5, [%i2 + 52]
  1476.     st        %l6, [%i2 + 56]
  1477.     st        %l7, [%i2 + 60]
  1478.  
  1479.     sub       %i0, 64, %i0
  1480.     add        %i1, 64, %i1
  1481.     add        %i2, 64, %i2
  1482.     ba         QWordCopy
  1483.     nop
  1484.  
  1485.     /*
  1486.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  1487.      * quickly by dispatching into the middle of a sequence of move
  1488.      * instructions, but I don't yet.
  1489.      */
  1490.  
  1491. QFinishWord:
  1492.     cmp        %i0, 4
  1493.     bl        QByteCopyIt
  1494.     nop
  1495.     /* from context */
  1496.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1497.  
  1498.     ld        [%i1], %l0
  1499.  
  1500.     /* to context */
  1501.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1502.  
  1503.     st        %l0, [%i2]
  1504.     sub        %i0, 4, %i0
  1505.     add        %i1, 4, %i1
  1506.     add        %i2, 4, %i2
  1507.     ba        QFinishWord
  1508.     nop
  1509.     
  1510.     /*
  1511.      * Do one byte copies until done.
  1512.      */
  1513. QByteCopyIt:
  1514.     tst        %i0
  1515.     ble         QDoneCopying
  1516.     nop
  1517.  
  1518.     /* from context */
  1519.     stba    %i3, [%i5] VMMACH_CONTROL_SPACE
  1520.  
  1521.     ldub    [%i1], %l0
  1522.  
  1523.     /* to context */
  1524.     stba    %i4, [%i5] VMMACH_CONTROL_SPACE
  1525.  
  1526.     stb        %l0, [%i2]
  1527.     sub        %i0, 1, %i0
  1528.     add        %i1, 1, %i1
  1529.     add        %i2, 1, %i2
  1530.     ba         QByteCopyIt
  1531.     nop
  1532.  
  1533.     /* 
  1534.      * Return.
  1535.      */
  1536.  
  1537. QDoneCopying: 
  1538.     clr        %i0    /* SUCCESS */
  1539.     ret
  1540.     restore
  1541.  
  1542. .globl _VmMachEndQuickCopy
  1543. _VmMachEndQuickCopy:
  1544.  
  1545.  
  1546.  
  1547. /*
  1548.  * ----------------------------------------------------------------------
  1549.  *
  1550.  * Vm_Copy{In,Out}
  1551.  *
  1552.  *    Copy numBytes from *sourcePtr in to *destPtr.
  1553.  *    This routine is optimized to do transfers when sourcePtr and 
  1554.  *    destPtr are both double-word aligned.
  1555.  *
  1556.  *    ReturnStatus
  1557.  *    Vm_Copy{In,Out}(numBytes, sourcePtr, destPtr)
  1558.  *        register int numBytes;      The number of bytes to copy
  1559.  *        Address sourcePtr;          Where to copy from.
  1560.  *        Address destPtr;            Where to copy to.
  1561.  *
  1562.  * Results:
  1563.  *    Returns SUCCESS if the copy went OK (which is almost always).  If
  1564.  *    a bus error (other than a page fault) occurred while reading or
  1565.  *    writing user memory, then SYS_ARG_NO_ACCESS is returned (this return
  1566.  *    occurs from the trap handler, rather than from this procedure).
  1567.  *
  1568.  * Side effects:
  1569.  *    The area that destPtr points to is modified.
  1570.  *
  1571.  * ----------------------------------------------------------------------
  1572.  */
  1573. .globl _VmMachDoCopy
  1574. .globl _Vm_CopyIn
  1575. _VmMachDoCopy:
  1576. _Vm_CopyIn:
  1577.                         /* numBytes in o0 */
  1578.                         /* sourcePtr in o1 */
  1579.                         /* destPtr in o2 */
  1580. /*
  1581.  * If the source or dest are not double-word aligned then everything must be
  1582.  * done as word or byte copies.
  1583.  */
  1584.  
  1585. GotArgs:
  1586.     or        %o1, %o2, %OUT_TEMP1
  1587.     andcc    %OUT_TEMP1, 7, %g0
  1588.     be        DoubleWordCopy
  1589.     nop
  1590.     andcc    %OUT_TEMP1, 3, %g0
  1591.     be        WordCopy
  1592.     nop
  1593.     ba        ByteCopyIt
  1594.     nop
  1595.  
  1596.     /*
  1597.      * Do as many 64-byte copies as possible.
  1598.      */
  1599.  
  1600. DoubleWordCopy:
  1601.     cmp        %o0, 64
  1602.     bl         FinishWord
  1603.     nop
  1604.     ldd        [%o1], %OUT_TEMP1    /* uses out_temp1 and out_temp2 */
  1605.     std        %OUT_TEMP1, [%o2]
  1606.     ldd        [%o1 + 8], %OUT_TEMP1
  1607.     std        %OUT_TEMP1, [%o2 + 8]
  1608.     ldd        [%o1 + 16], %OUT_TEMP1
  1609.     std        %OUT_TEMP1, [%o2 + 16]
  1610.     ldd        [%o1 + 24], %OUT_TEMP1
  1611.     std        %OUT_TEMP1, [%o2 + 24]
  1612.     ldd        [%o1 + 32], %OUT_TEMP1
  1613.     std        %OUT_TEMP1, [%o2 + 32]
  1614.     ldd        [%o1 + 40], %OUT_TEMP1
  1615.     std        %OUT_TEMP1, [%o2 + 40]
  1616.     ldd        [%o1 + 48], %OUT_TEMP1
  1617.     std        %OUT_TEMP1, [%o2 + 48]
  1618.     ldd        [%o1 + 56], %OUT_TEMP1
  1619.     std        %OUT_TEMP1, [%o2 + 56]
  1620.     
  1621.     sub       %o0, 64, %o0
  1622.     add        %o1, 64, %o1
  1623.     add        %o2, 64, %o2
  1624.     ba         DoubleWordCopy
  1625.     nop
  1626. WordCopy:
  1627.     cmp        %o0, 64
  1628.     bl        FinishWord
  1629.     nop
  1630.     ld        [%o1], %OUT_TEMP1
  1631.     st        %OUT_TEMP1, [%o2]
  1632.     ld        [%o1 + 4], %OUT_TEMP1
  1633.     st        %OUT_TEMP1, [%o2 + 4]
  1634.     ld        [%o1 + 8], %OUT_TEMP1
  1635.     st        %OUT_TEMP1, [%o2 + 8]
  1636.     ld        [%o1 + 12], %OUT_TEMP1
  1637.     st        %OUT_TEMP1, [%o2 + 12]
  1638.     ld        [%o1 + 16], %OUT_TEMP1
  1639.     st        %OUT_TEMP1, [%o2 + 16]
  1640.     ld        [%o1 + 20], %OUT_TEMP1
  1641.     st        %OUT_TEMP1, [%o2 + 20]
  1642.     ld        [%o1 + 24], %OUT_TEMP1
  1643.     st        %OUT_TEMP1, [%o2 + 24]
  1644.     ld        [%o1 + 28], %OUT_TEMP1
  1645.     st        %OUT_TEMP1, [%o2 + 28]
  1646.     ld        [%o1 + 32], %OUT_TEMP1
  1647.     st        %OUT_TEMP1, [%o2 + 32]
  1648.     ld        [%o1 + 36], %OUT_TEMP1
  1649.     st        %OUT_TEMP1, [%o2 + 36]
  1650.     ld        [%o1 + 40], %OUT_TEMP1
  1651.     st        %OUT_TEMP1, [%o2 + 40]
  1652.     ld        [%o1 + 44], %OUT_TEMP1
  1653.     st        %OUT_TEMP1, [%o2 + 44]
  1654.     ld        [%o1 + 48], %OUT_TEMP1
  1655.     st        %OUT_TEMP1, [%o2 + 48]
  1656.     ld        [%o1 + 52], %OUT_TEMP1
  1657.     st        %OUT_TEMP1, [%o2 + 52]
  1658.     ld        [%o1 + 56], %OUT_TEMP1
  1659.     st        %OUT_TEMP1, [%o2 + 56]
  1660.     ld        [%o1 + 60], %OUT_TEMP1
  1661.     st        %OUT_TEMP1, [%o2 + 60]
  1662.     
  1663.     sub       %o0, 64, %o0
  1664.     add        %o1, 64, %o1
  1665.     add        %o2, 64, %o2
  1666.     ba         WordCopy
  1667.     nop
  1668.  
  1669.     /*
  1670.      * Copy up to 64 bytes of remainder, in 4-byte chunks.  I SHOULD do this
  1671.      * quickly by dispatching into the middle of a sequence of move
  1672.      * instructions, but I don't yet.
  1673.      */
  1674.  
  1675. FinishWord:
  1676.     cmp        %o0, 4
  1677.     bl        ByteCopyIt
  1678.     nop
  1679.     ld        [%o1], %OUT_TEMP1
  1680.     st        %OUT_TEMP1, [%o2]
  1681.     sub        %o0, 4, %o0
  1682.     add        %o1, 4, %o1
  1683.     add        %o2, 4, %o2
  1684.     ba        FinishWord
  1685.     nop
  1686.     
  1687.     /*
  1688.      * Do one byte copies until done.
  1689.      */
  1690. ByteCopyIt:
  1691.     tst        %o0
  1692.     ble         DoneCopying
  1693.     nop
  1694.     ldub    [%o1], %OUT_TEMP1
  1695.     stb        %OUT_TEMP1, [%o2]
  1696.     sub        %o0, 1, %o0
  1697.     add        %o1, 1, %o1
  1698.     add        %o2, 1, %o2
  1699.     ba         ByteCopyIt
  1700.     nop
  1701.  
  1702.     /* 
  1703.      * Return.
  1704.      */
  1705.  
  1706. DoneCopying: 
  1707.     clr        %o0
  1708.     retl        /* return from leaf routine */
  1709.     nop
  1710.  
  1711. /*
  1712.  * Vm_CopyOut is just like Vm_CopyIn except that it checks to make sure
  1713.  * that the destination is in the user area (otherwise this would be a
  1714.  * trap door to write to kernel space).
  1715.  */
  1716.  
  1717. .globl _Vm_CopyOut, _mach_FirstUserAddr, _mach_LastUserAddr
  1718. _Vm_CopyOut:
  1719.                         /* numBytes in o0 */
  1720.                         /* sourcePtr in o1 */
  1721.                         /* destPtr in o2 */
  1722.     set        _mach_FirstUserAddr, %OUT_TEMP1
  1723.     ld        [%OUT_TEMP1], %OUT_TEMP1    /* get 1st user addr */
  1724.     cmp        %o2, %OUT_TEMP1
  1725.     blu        BadAddress        /* branch carry set */
  1726.     nop
  1727.     sub        %o2, 1, %OUT_TEMP2
  1728.     addcc    %OUT_TEMP2, %o0, %OUT_TEMP2
  1729.     blu        BadAddress
  1730.     nop
  1731.  
  1732.     set        _mach_LastUserAddr, %OUT_TEMP1
  1733.     ld        [%OUT_TEMP1], %OUT_TEMP1
  1734.     cmp        %OUT_TEMP2, %OUT_TEMP1
  1735.     bleu    GotArgs
  1736.     nop
  1737.  
  1738.     /*
  1739.      * User address out of range.  Check for a zero byte count before
  1740.      * returning an error, though;  there appear to be kernel routines
  1741.      * that call Vm_CopyOut with a zero count but bogus other arguments.
  1742.      */
  1743.  
  1744. BadAddress:
  1745.     tst        %o0
  1746.     bne        BadAddressTruly
  1747.     clr        %RETURN_VAL_REG
  1748.     retl
  1749.     nop
  1750. BadAddressTruly:
  1751.     set        SYS_ARG_NOACCESS, %RETURN_VAL_REG
  1752.     retl
  1753.     nop
  1754.  
  1755. /*
  1756.  * ----------------------------------------------------------------------
  1757.  *
  1758.  * Vm_StringNCopy
  1759.  *
  1760.  *    Copy the NULL terminated string from *sourcePtr to *destPtr up
  1761.  *    numBytes worth of bytes.
  1762.  *
  1763.  *    void
  1764.  *    Vm_StringNCopy(numBytes, sourcePtr, destPtr, bytesCopiedPtr)
  1765.  *        register int numBytes;      The number of bytes to copy
  1766.  *        Address sourcePtr;          Where to copy from.
  1767.  *        Address destPtr;            Where to copy to.
  1768.  *        int    *bytesCopiedPtr;    Number of bytes copied.
  1769.  *
  1770.  *    NOTE: The trap handler assumes that this routine does not push anything
  1771.  *          onto the stack.  It uses this fact to allow it to return to the
  1772.  *          caller of this routine upon an address fault.  If you must push
  1773.  *          something onto the stack then you had better go and modify 
  1774.  *          "CallTrapHandler" in asmDefs.h appropriately.
  1775.  *
  1776.  * Results:
  1777.  *    Normally returns SUCCESS.  If a non-recoverable bus error occurs,
  1778.  *    then the trap handler fakes up a SYS_ARG_NO_ACCESS return from
  1779.  *    this procedure.
  1780.  *
  1781.  * Side effects:
  1782.  *    The area that destPtr points to is modified and *bytesCopiedPtr 
  1783.  *    contains the number of bytes copied.  NOTE: this always copies
  1784.  *    at least one char, even if the numBytes param is zero!!!
  1785.  *
  1786.  * ----------------------------------------------------------------------
  1787.  */
  1788. .globl  _Vm_StringNCopy
  1789. _Vm_StringNCopy:
  1790.                         /* numBytes in o0 */
  1791.                         /* sourcePtr in o1 */
  1792.                         /* destPtr in o2 */
  1793.                         /* bytesCopiedPtr in o3 */
  1794.  
  1795.     mov        %o0, %OUT_TEMP2            /* save numBytes */
  1796. StartCopyingChars: 
  1797.     ldub    [%o1], %OUT_TEMP1        /* Copy the character */
  1798.     stb        %OUT_TEMP1, [%o2]
  1799.     add        %o1, 1, %o1            /* increment addresses */
  1800.     add        %o2, 1, %o2
  1801.     cmp        %OUT_TEMP1, 0            /* See if hit null in string. */
  1802.     be        NullChar
  1803.     nop
  1804.  
  1805.     subcc    %OUT_TEMP2, 1, %OUT_TEMP2    /* Decrement the byte counter */
  1806.     bne        StartCopyingChars        /* Copy more chars if haven't */
  1807.     nop                     /*     reached the limit. */
  1808. NullChar: 
  1809.     sub        %o0, %OUT_TEMP2, %OUT_TEMP2    /* Compute # of bytes copied */
  1810.     st        %OUT_TEMP2, [%o3]         /* and store the result. */
  1811.     clr     %RETURN_VAL_REG            /* Return SUCCESS. */
  1812.     retl
  1813.     nop
  1814.  
  1815.  
  1816. /*
  1817.  * ----------------------------------------------------------------------
  1818.  *
  1819.  * Vm_TouchPages --
  1820.  *
  1821.  *    Touch the range of pages.
  1822.  *
  1823.  *    ReturnStatus
  1824.  *    Vm_TouchPages(firstPage, numPages)
  1825.  *        int    firstPage;    First page to touch.
  1826.  *        int    numPages;    Number of pages to touch.
  1827.  *
  1828.  *    NOTE: The trap handler assumes that this routine does not push anything
  1829.  *          onto the stack.  It uses this fact to allow it to return to the
  1830.  *          caller of this routine upon an address fault.  If you must push
  1831.  *          something onto the stack then you had better go and modify 
  1832.  *          "CallTrapHandler" in asmDefs.h appropriately.
  1833.  *
  1834.  * Results:
  1835.  *    Returns SUCCESS if we're able to touch the page (which is almost
  1836.  *    always).  If a bus error (other than a page fault) occurred while 
  1837.  *    reading user memory, then SYS_ARG_NO_ACCESS is returned (this return
  1838.  *    occurs from the trap handler, rather than from this procedure).
  1839.  *
  1840.  * Side effects:
  1841.  *    None.
  1842.  *
  1843.  * ----------------------------------------------------------------------
  1844.  */
  1845. .globl _Vm_TouchPages
  1846. _Vm_TouchPages:
  1847.                 /* o0 = first page = starting addr */
  1848.                 /* o1 = numPages */
  1849.     set        VMMACH_PAGE_SHIFT, %OUT_TEMP1
  1850.     sll        %o0, %OUT_TEMP1, %o0    /* o0 = o0 << VMMACH_PAGE_SHIFT */
  1851.     /* Mike had arithmetic shift here, why??? */
  1852. StartTouchingPages:
  1853.     tst        %o1        /* Quit when %o1 == 0 */
  1854.     be        DoneTouchingPages
  1855.     nop
  1856.     ld        [%o0], %OUT_TEMP1    /* Touch page at addr in %o0 */
  1857.     sub        %o1, 1, %o1    /* Go back around to touch the next page. */
  1858.     set        VMMACH_PAGE_SIZE, %OUT_TEMP2
  1859.     add        %o0, %OUT_TEMP2, %o0
  1860.     ba        StartTouchingPages
  1861.     nop
  1862.  
  1863. DoneTouchingPages:
  1864.     clr        %RETURN_VAL_REG        /* return success */
  1865.     retl
  1866.     nop
  1867.  
  1868. /*
  1869.  * The address marker below is there so that the trap handler knows the
  1870.  * end of code that may take a page fault while copying into/out of
  1871.  * user space.
  1872.  */
  1873.  
  1874. .globl    _VmMachCopyEnd
  1875. _VmMachCopyEnd:
  1876.